#include "heart_impl.h"
#include "../global/head.h"
#include "../xos/head.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos
{
    heart_impl::heart_impl()
    {
        m_iScanInterval = 20;
        m_bQuit = false;
        m_pThread = 0;
        m_pEvent = 0;
    }

    heart_impl::~heart_impl()
    {
        term();
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    int heart_impl::init()
    {
        int nRet = 0;

        if( 0 == nRet )
        {
            nRet = g_pXosImpl->create( i_xos::XOS_OBJ_EVENT, ( void ** )&m_pEvent );
        }

        if( 0 == nRet )
        {
            nRet = g_pXosImpl->create( i_xos::XOS_OBJ_THREAD, ( void ** )&m_pThread );
            if( 0 == nRet )
            {
                nRet = m_pThread->create( thread, this );
            }
        }

        return nRet;
    }

    int heart_impl::term() 
    {
        int nRet = 0;

        if( m_pThread )
        {
            m_bQuit = true;
            m_pEvent->set_event();
            m_pThread->wait();
            m_pThread->release();
            m_pThread = 0;
            m_iScanInterval = 20;
            m_bQuit = false;
        }

        if( m_pEvent )
        {
            m_pEvent->release();
            m_pEvent = 0;
        }

        m_accept_list.put_back_to_pool();

        return nRet;
    }

    void * heart_impl::thread( void * lpData )
    {
        heart_impl & obj = *( heart_impl * )lpData;

        while( !obj.m_bQuit )
        {
            obj.m_pEvent->wait( obj.m_iScanInterval );

            if( !obj.m_bQuit )
            {
                obj.scan();
            }
        }

        return 0;
    }

    int heart_impl::scan()
    {
        int nRet = 0;

        m_lock.lock();

        for( heart_acceptor * p = m_accept_list.begin(); p != m_accept_list.end(); p = p->m_pNext )
        {
            p->m_iCurTime += m_iScanInterval;

            if( p->m_iCurTime >= p->m_iInterval )
            {
                p->m_iCurTime = 0;
                p->m_pAcceptor->heart_call();
            }
        }

        m_lock.un_lock();

        return nRet;
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // set heart interval
    // 
    int heart_impl::set_interval( xos_i32 iMilliSecondInterval )
    {
        int nRet = 0;
        m_iScanInterval = iMilliSecondInterval;
        return nRet;
    }

    // 
    // add acceptor
    // 
    int heart_impl::add_acceptor( i_acceptor * pAcceptor, xos_i32 iInterval )
    {
        int nRet = 0;

        heart_acceptor * pFind = 0;

        if( !pAcceptor )
        {
            return 1;
        }

        m_lock.lock();

        for( heart_acceptor * p = m_accept_list.begin(); p != m_accept_list.end(); p = p->m_pNext )
        {
            if( p->m_pAcceptor == pAcceptor )
            {
                pFind = p;
                break;
            }
        }

        if( !pFind )
        {
            nRet = g_pXosImpl->create( i_xos::XOS_OBJ_ACCEPTOR, ( void ** )&pFind );
            if( 0 == nRet )
            {
                m_accept_list.push_back( pFind );
            }
        }

        if( pFind )
        {
            pFind->m_pAcceptor = pAcceptor;
            pFind->m_iInterval = iInterval;
        }

        m_lock.un_lock();

        return nRet;
    }

    // 
    // remove acceptor
    // 
    int heart_impl::rem_acceptor( i_acceptor * pAcceptor )
    {
        int nRet = 0;

        heart_acceptor * pFind = 0;

        if( !pAcceptor )
        {
            return 1;
        }

        m_lock.lock();

        for( heart_acceptor * p = m_accept_list.begin(); p != m_accept_list.end(); p = p->m_pNext )
        {
            if( p->m_pAcceptor == pAcceptor )
            {
                pFind = p;
                break;
            }
        }

        if( pFind )
        {
            m_accept_list.remove( pFind );
            pFind->release();
            pFind = 0;
        }

        m_lock.un_lock();

        return nRet;
    }

    // 
    // release
    // 
    int heart_impl::release()
    {
        int nRet = 0;

        term();
        put_back_lock();

        return nRet;
    }
} // xos
